<template>
  <div id="EditableTable">
    <el-table :summary-method="getSummaries" 
    show-summary :data="tableData" border>
      <el-table-column :label="col.label" :prop="col.prop" v-for="(col,colIndex) in columnList" :key="colIndex" align="center">
        <template slot-scope="scope">
          <template v-if="colIndex > 0">
            <el-input v-if="colIndex==activeCell[0]&& scope.$index == activeCell[1]" ref="activeInput" :min="0" :value="tableData[scope.$index][col.prop]" @input="value => handleInputChange(value,scope.$index,col.prop)" @blur="handleInputBlur(tableData[scope.$index][col.prop],scope.$index,col.prop)"></el-input>
            <span :class="['textCell',disableJobInjury(scope.row.projectName,col.prop)?'disabledCell':'']" v-else @click="handleChangeActiveCell(colIndex,scope.row[col.prop],scope.$index,col.prop)">{{scope.row[col.prop]}}</span>
          </template>

          <!-- 首行不需要显示输入框 -->
          <span v-else class="textCell">{{scope.row[col.prop] == '公积金'?'住房公积金':scope.row[col.prop]}}</span>
        </template>
      </el-table-column>
      <el-table-column label="合计" prop="totalAmount"></el-table-column>
    </el-table>
  </div>
</template>
<script>
import { math } from '@/util/math.js';
export default {
  name: 'EditableTable',
  props: {
    type: {
      type: Number, // 1--社保明细 2--公积金明细
      default: 1
    },
    tableData: {
      type: Array,
      default: () => {
        return [{ baseNumber: '1' }];
      }
    },
    // 表格是否可编辑
    isEditable: {
      type: Boolean,
      default: true

    }

  },
  data() {
    return {
      activeCell: [-1, -1],

    };
  },
  computed: {
    columnList() {
      const typeName = this.type == 1 ? '社保' : '公积金';
      let list = [
        { label: `${typeName}项目`, prop: 'projectName', },
        { label: `${typeName}基数`, prop: 'baseNumber' },
        { label: '个人比例', prop: 'personalRatio' },
        { label: '公司比例', prop: 'companyRatio' },
        { label: '个人承担金额', prop: 'personalAmount' },
        { label: '公司承担金额', prop: 'companyAmount' },
      ];
      return list;
    }
  },
  methods: {
    // 使用summary-method  自定义的合计逻辑。主要是为了显示订单合计金额，并过滤不需要合计的列
    getSummaries(param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        // 第一列 显示文字 小计
        if (index === 0) {
          sums[index] = '合计';
          return;
        }
        // console.log('index----------',index);
        if ([4, 5, 6].includes(index)) { // 只针对金额列进行合计
          const values = data.map(item => Number(item[column.property]));
          console.log('values', values);
          if (!values.every(value => isNaN(value))) {
            sums[index] = values.reduce((prev, curr) => {
              const value = Number(curr);
              if (!isNaN(value)) {
                return prev + curr;
              } else {
                return prev;
              }
            }, 0);
            // console.log('sums[index]',sums[index]);
            sums[index] = math.toFixed(sums[index]); // 保留2位小数，解决小数合计列
          } else {
            sums[index] = 100; // 其余列一律不进行合计
          }
        }
      });
      return sums;
    },

    /**
     * @description 点击表格项，打开对应位置的输入框
     * @param colIndex 列下标
     * @param value 单元格内数据
     * @param index 行下标
     * @param prop 列属性名
     */
    handleChangeActiveCell(colIndex, value, index, prop) {
      // 如果isEditable为false，不可编辑
      if(!this.isEditable) return false;

      // 如果点击的是工伤个人比例和个人承担金额，不打开输入框
      if (this.disableJobInjury(this.tableData[index].projectName, prop)) return;


      // 打开输入框前，对值进行一次规范处理
      // 如果 值为0，0%，null 输入框内不显示值
      if (!value || ['0', '0.00', 0, '0%'].includes(value)) {
        value = '';
      }
      this.$set(this.tableData[index], prop, this.formatInputValue(value));

      // 打开输入框
      this.activeCell = [colIndex, index];
      this.$nextTick(() => {
        this.$refs.activeInput[0].focus();
      });
    },

    /**
     * @description 表格内输入框值变化后触发方法
     * @param value 输入框修改后值
     * @param index 当前输入框所在行下标
     * @param prop 当前修改字段名
     */
    handleInputChange(value, index, prop) {
      this.$set(this.tableData[index], prop, this.formatInputValue(value));
    },

    /**
     * @description 表格内输入框失焦后触发
     * @param 与handleInputChange相同
     */
    handleInputBlur(value, index, prop) {
      if (value.length == 0) {
        value = 0;
      }
      // 当修改的是比例时，对数据进行处理
      if (prop == 'personalRatio' || prop == 'companyRatio') {
        value = value + '%';
      } else {
        value = math.toFixed(Number.parseFloat(value));
      }
      // if (prop == 'baseNumber') {

      //   console.log(value);
      // }
      // 将值同步到tableData中
      this.$set(this.tableData[index], prop, value);

      this.computeRowData(index, prop);
      // 关闭输入框
      this.activeCell = [-1, -1];
    },

    /**
     * @description 对数据进行规范处理 精确到小数点后两位
     */
    formatInputValue(value) {
      const reg = /^\D*(\d*(?:\.\d{0,2})?).*$/g; //精确到小数点后二位
      value = (value + '').replace(reg, '$1');
      return value;
    },

    /**
     * @description 在每次修改行内数据后，根据修改后值对当前行其他数据进行同步修改
     * @param index 当前修改行
     * @param prop 当前行被修改的字段
     */
    computeRowData(index, prop) {
      let row = this.tableData[index];
      let proportion = 0;
      const boundaryValue = ['0', 0, '0.0', '0.00'];
      switch (prop) {
        case 'personalRatio': // 修改的是个人比例
          // 个人承担金额跟随变动
          row.personalAmount = math.toFixed(math.multiply(row.baseNumber, this.transformPercentage(row.personalRatio, 1)));
          break;
        case 'companyRatio': // 修改的是公司比例
          //公司承担金额跟随变动 
          row.companyAmount = math.toFixed(math.multiply(row.baseNumber, this.transformPercentage(row.companyRatio, 1)));
          break;
        case 'baseNumber': //修改的是基数
          // console.log('基数变动',math.toFixed(math.multiply(row.baseNumber, this.transformPercentage(row.personalRatio, 1))));
          // 个人承担和公司承担金额跟随变动
          row.personalAmount = math.toFixed(math.multiply(row.baseNumber, this.transformPercentage(row.personalRatio, 1)));
          row.companyAmount = math.toFixed(math.multiply(row.baseNumber, this.transformPercentage(row.companyRatio, 1)));
          break;
        // case 'personalAmount': // 修改的是个人承担金额
        //   //个人比例跟随变动
        //   // 处理基数与承担金额都为0计算结构为NaN问题
        //   if(boundaryValue.includes(row.baseNumber) && boundaryValue.includes(row.personalAmount)) {
        //     row.personalRatio = '0%';
        //     break;
        //   }
        //   // console.log(row.personalAmount, row.baseNumber);
        //   proportion = math.divide(row.personalAmount, row.baseNumber).toFixed(2);
        //   row.personalRatio = this.transformPercentage(proportion, 2);
        //   break;
        // case 'companyAmount': // 修改的是公司承担金额
        //   // 公司比例跟随变动
        //   // 处理基数与承担金额都为0计算结构为NaN问题
        //   if(boundaryValue.includes(row.baseNumber) && boundaryValue.includes(row.companyAmount)) {
        //     row.companyRatio = '0%';
        //     break;
        //   }
        //   proportion = math.divide(row.companyAmount, row.baseNumber).toFixed(2);
        //   row.companyRatio = this.transformPercentage(proportion, 2);
        //   break;
      }
      // 修改完成后，对当行合计列值进行计算
      row.totalAmount = math.toFixed(math.add(row.personalAmount, row.companyAmount));

      // 将修改后数据同步到父组件列表数据中
      this.$set(this.tableData, index, row);
    },

    /**
     * @description 将在表格中输入的 百分比 与小数之间互相转换
     * @param value 待转换值
     * @param type 待转换值的类型 1--百分比（显示在表格中） 2--小数（用于计算）
     */
    transformPercentage(value, type) {
      if (type == 1) {
        // 去除百分号
        // console.log(value,'transformPercentage-value');
        value = math.divide(value.replace('%', ''), 100);
        // console.log('进行值换算', value);
        // 计算成小数（保留两位）后返回
        return value;
      } else {
        return math.multiply(value, 100) + '%';
      }
    },

    /**
     * @description 提供给父组件，用来将表格数据在可提交类型（将比例，总额等数据转为数字）和显示类型相互转化的方法
     * @param data 待转换数据
     * @param conversionType 要转换成什么类型 1--转换为可提交类型 2--转换为显示类型
     * @returns {Object} 返回转换后数据
     */
    formatTableData(data, conversionType = 1) {
      if (conversionType == 1) {
        // 将两个列表中数据进行格式化
        ['ssRuleItemList', 'afRuleItemList'].map(prop => {
          data[prop] = data[prop].map(e => {

            // 格式化个人比例与公司比例
            if (e.personalRatio.indexOf('%') !== -1) {
              e.personalRatio = this.transformPercentage(e.personalRatio, 1);
            }
            if (e.companyRatio.indexOf('%') !== -1) {
              e.companyRatio = this.transformPercentage(e.companyRatio, 1);
            }
            // 格式化合计,基数，个人承担金额，公司承担金额
            ['totalAmount', 'baseNumber', 'personalAmount', 'companyAmount'].map(eProp => {
              // if (typeof e[eProp] == 'string') {
              // console.log('e[eProp]', e[eProp]);
              e[eProp] = parseFloat(e[eProp]);
              // }
            });
            // 
            return e;
          });
        });

      } else {
        ['ssRuleItemList', 'afRuleItemList'].map(prop => {
          data[prop] = data[prop].map(e => {

            // 格式化个人比例与公司比例
            e.personalRatio = math.multiply(e.personalRatio, 100) + '%';
            e.companyRatio = math.multiply(e.companyRatio, 100) + '%';
            // 格式化合计,基数，个人承担金额，公司承担金额
            ['totalAmount', 'baseNumber', 'personalAmount', 'companyAmount'].map(eProp => {
              e[eProp] = math.toFixed(e[eProp]);
            });
            return e;
          });
        });
      }
      return data;
    },

    disableJobInjury(projectName, colProp) {
      if (projectName !== '工伤') return false;
      if (colProp != 'personalRatio' && colProp != 'personalAmount') return false;
      return true;
    }

  }
};
</script>
<style lang="less" scoped>
#EditableTable {
  .textCell {
    display: inline-block;
    width: 100%;
    height: 24px;
    line-height: 24px;
    text-align: center;
  }
  .disabledCell {
    cursor: not-allowed;
  }
  :deep(.el-table) {
    .cell {
      text-align: center;
    }
    .el-input {
      .el-input__inner {
        text-align: center;
        height: 22px;
        line-height: 22px;
        margin: 0;
        font-size: 12px;
        box-sizing: border-box;
      }
    }
  }
}
</style>